let dbUtil = require('db-util')
const uniID = require('uni-id')
let db = uniCloud.database()
let dbCmd = db.command
let $ = dbCmd.aggregate
const errParams = {
	errCode: 500,
	errMsg: '参数错误！'
}
const errResNotFound = {
	errCode: 501,
	errMsg: '实体不存在！'
}
const moment = require('moment-timezone')
function formatTime(time) {
	if (typeof time !== 'number' || time < 0) {
		return time
	}

	var hour = parseInt(time / 3600)
	time = time % 3600
	var minute = parseInt(time / 60)
	time = time % 60
	var second = time

	return ([hour, minute, second]).map(function (n) {
		n = n.toString()
		return n[1] ? n : '0' + n
	}).join(':')
}
function getDistance(loc1, loc2) {
	let la1 = loc1.latitude,
		la2 = loc2.latitude,
		lo1 = loc1.longitude,
		lo2 = loc2.longitude
	var La1 = la1 * Math.PI / 180.0
	var La2 = la2 * Math.PI / 180.0
	var La3 = La1 - La2
	var Lb3 = lo1 * Math.PI / 180.0 - lo2 * Math.PI / 180.0;
	let s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(La3 / 2), 2) + Math.cos(La1) * Math.cos(La2) * Math
		.pow(Math.sin(Lb3 / 2), 2))) * 6378137
	return s
}
module.exports = {
	_before: async function() { // 通用预处理器
		const token = this.getUniIdToken()
		if (!token) {
			throw new Error('未登录')
		}
		const payload = await uniID.checkToken(token)
		let {
			code,
			uid,
			permission,
			userInfo
		} = payload
		if (code) {
			throw new Error('未登录')
		}
		this.userInfo = userInfo
		this.uid = uid
		if (!permission) {
			permission = await uniID.getPermissionByUid({
				uid
			})
		}
		this.permission = permission
		let roleRes = await uniID.getRoleByUid({
			uid
		})
		if (roleRes.code != 0) {
			throw new Error(roleRes.msg)
		}
		this.roles = roleRes.role
		console.log('roles', this.roles, this.permission)
		const methodName = this.getMethodName()
		let isAdmin = this.roles.some(item => item == 'admin')
		if (methodName == 'checkTask' && this.permission.indexOf('task:check') == -1 && !isAdmin) {
			throw new Error('无权限')
		}
	},
	
	async revert(taskDetailId) {
		if (!taskDetailId) {
			return {
				errCode: 500,
				errMsg: '参数错误！'
			}
		}
		let taskUser = await dbUtil.getById({
			collection: 't3ds-marketing-task-user',
			id: taskDetailId
		})
		if (!taskUser) {
			return {
				errCode: 500,
				errMsg: '任务不存在！'
			}
		}
		let transaction = await db.startTransaction()
		try {
			await dbUtil.removeById({
				collection: 't3ds-marketing-task-user',
				id: taskDetailId,
				transaction
			})
			await dbUtil.updateById({
				collection: 't3ds-marketing-task',
				data: {
					_id: taskUser.taskId,
					remainCount: dbCmd.inc(1)
				},
				transaction
			})
			await dbUtil.updateById({
				collection: 't3ds-marketing-task-asset',
				data: {
					_id: taskUser.assetId,
					used: false,
					createBy: dbCmd.remove(),
					createTime: dbCmd.remove()
				},
				transaction
			})
			await transaction.commit()
			return {
				errCode: 0,
			}
		} catch (err) {
			await transaction.rollback()
			return {
				errCode: 500,
				errMsg: err.message
			}
		}
	},
	
	async checkTask(taskDetailId, checkStatus, checkMsg, enableCheckLocation = false) {
		if (!taskDetailId || !checkStatus || [1, 2, -1, 3].indexOf(checkStatus) == -1 || (checkStatus == -1 && !checkMsg)) {
			return {
				errCode: 500,
				errMsg: '参数错误！'
			}
		}
		let taskUser = await dbUtil.getById({
			collection: 't3ds-marketing-task-user',
			id: taskDetailId
		})
		if (!taskUser) {
			return {
				errCode: 500,
				errMsg: '任务不存在！'
			}
		}
		let task = await dbUtil.getById({
			collection: 't3ds-marketing-task',
			id: taskUser.taskId
		})
		if (!task) {
			return {
				errCode: 500,
				errMsg: '任务已下线！'
			}
		}
		let transaction = await db.startTransaction()
		try {
			let r = taskUser.checkRecords ? taskUser.checkRecords[taskUser.checkRecords.length - 1] : {}
			r.checkStatus = checkStatus
			r.checkTime = Date.now()
			r.checkBy = this.uid
			r.checkMsg = checkMsg
			let data = {
				['checkRecords.' + (taskUser.checkRecords.length - 1)]: r,
				checkStatus:checkStatus
			}
			if (task.checkLocation && taskUser.enableCheckLocation == false && enableCheckLocation == true) {
				data.enableCheckLocation = true
			}
			await transaction.collection('t3ds-marketing-task-user')
				.doc(taskDetailId)
				.update(data)
			if ((checkStatus == 2||checkStatus==-1) && task.rewards > 0) {
				let integral = await dbUtil.getOne({
					collection: 't3ds-integral',
					where: {
						uid: taskUser.uid,
						storeId: task.storeId
					}
				})
				if (integral) {
					await dbUtil.updateById({
						collection: 't3ds-integral',
						data: {
							_id: integral._id,
							balance: dbCmd.inc(task.rewards),
							total: dbCmd.inc(task.rewards)
						},
						transaction
					})
				} else {
					integral = {
						uid: taskUser.uid,
						storeId: task.storeId,
						balance: task.rewards,
						total: task.rewards
					}
					await dbUtil.insert({
						collection: 't3ds-integral',
						data: integral,
						transaction
					})
				}
				
					await dbUtil.insert({
						collection: 't3ds-integral-log',
						data: {
							uid: taskUser.uid,
							storeId: task.storeId,
							type: 2,
							balance: integral.balance + task.rewards,
							income: task.rewards,
							createTime: Date.now(),
							createBy: taskUser.uid,
							bizId: taskUser._id,
							note: `完成任务《${task.title}》`
						},
						transaction
					})
				
			
			}
			
			if ((checkStatus == 2||checkStatus==-1) && task.rewards2 > 0) {
				let account = await dbUtil.getOne({
					collection: 't3ds-account',
					where: {
						userId: taskUser.uid
					}
				})
				account.balance += task.rewards2
				account.total += task.rewards2
				await dbUtil.updateById({
					collection: 't3ds-account',
					data: account,
					transaction
				})
				await dbUtil.insert({
					collection: "t3ds-account-log",
					data: {
						accountId: account._id,
						total: account.total,
						income: task.rewards2,
						tradeType: 14,
						settled: true,
						createTime: Date.now(),
						createBy: this.uid
					}
				}, transaction);
			}
			
		
			
			
			
			await transaction.commit()
			return {
				errCode: 0,
			}
		} catch (err) {
			await transaction.rollback()
			return {
				errCode: 500,
				errMsg: err.message
			}
		}
	},

	async receiveTask(taskId) {
		if (!taskId) {
			return {
				errCode: 500,
				errMsg: '参数错误！'
			}
		}
		let task = await dbUtil.getById({
			collection: 't3ds-marketing-task',
			id: taskId
		})
		if (!task) {
			return {
				errCode: 500,
				errMsg: '任务不存在！'
			}
		}
		if (task.checkUserID !== false && (!this.userInfo.realname_auth || this.userInfo.realname_auth.auth_status != 2)) {
			return {
				errCode: 505,
				errMsg: '请先完成实名认证！ '
			}
		}
		if (task.remainCount == 0) {
			return {
				errCode: 501,
				errMsg: '任务已领完！'
			}
		}
		if (task.deadline < Date.now()) {
			return {
				errCode: 505,
				errMsg: '任务已失效，无法领取！'
			}
		}
		//查询同类型未完成的任务
		let userTaskRes = await db.collection('t3ds-marketing-task-user')
			.aggregate()
			.match({
				uid: this.uid,
				deadline: dbCmd.gte(Date.now()).or(dbCmd.exists(false))
			})
			.lookup({
				from: 't3ds-marketing-task',
				foreignField: '_id',
				localField: 'taskId',
				as: 'task'
			})
			.unwind('$task')
			.match({
				'task.typeId': task.typeId
			})
			.project({
				checkRecord: $.arrayElemAt(['$checkRecords', -1])
			})
			.match({
				'checkRecord.checkStatus': dbCmd.neq(2)
			})
			.end()
		if (userTaskRes.data.length) {
			return {
				errCode: 502,
				errMsg: '请先完成已有任务！'
			}
		}
		//查询同类型已完成的任务
		userTaskRes = await db.collection('t3ds-marketing-task-user')
			.aggregate()
			.match({
				uid: this.uid
			})
			.lookup({
				from: 't3ds-marketing-task',
				foreignField: '_id',
				localField: 'taskId',
				as: 'task'
			})
			.unwind('$task')
			.match({
				'task.typeId': task.typeId,
				checkRecords: dbCmd.exists(true)
			})
			.project({
				checkRecord: $.arrayElemAt(['$checkRecords', -1])
			})
			.match({
				'checkRecord.checkStatus': dbCmd.eq(2)
			})
			.sort({
				'checkRecord.checkTime': -1
			})
			.limit(1)
			.end()
		if (userTaskRes.data.length) {
			let startTime = userTaskRes.data[0].checkRecord.checkTime
			let type = await dbUtil.getById({
				collection: 't3ds-marketing-task-type',
				id: task.typeId
			})
			let span = type.frequency * 24 * 60 * 60 * 1000
			let validTime = startTime + span
			if (validTime > Date.now()) {
				moment.locale('zh', {
					relativeTime : {
						future: "在%s",
						past:   "%s之前",
						s  : '几秒钟',
						ss : '%d秒',
						m:  "1分钟",
						mm: "%d 分钟",
						h:  "1小时",
						hh: "%d小时",
						d:  "1天",
						dd: "%d天",
						w:  "1周",
						ww: "%d周",
						M:  "1个月",
						MM: "%d个月",
						y:  "1年",
						yy: "%d年"
					}
				})
				moment.locale('zh')
				let tip = moment(validTime).toNow(true)
				return {
					errCode: 503,
					errMsg: `${tip}后才能领取此任务`
				}
			}
		}
		
		let assetCount = await dbUtil.getCount({
			collection: 't3ds-marketing-task-asset',
			where: {
				taskId
			}
		})
		if (!assetCount) {
			return {
				errCode: 503,
				errMsg: '任务未配置素材，请联系管理员！'
			}
		}
		if (task.multiAsset) {
			assetCount = await dbUtil.getCount({
				collection: 't3ds-marketing-task-asset',
				where: {
					taskId,
					used: false
				}
			})
			if (!assetCount) {
				return {
					errCode: 504,
					errMsg: '任务未配置素材，请联系管理员！'
				}
			}
		}
		let transaction = await db.startTransaction()
		try {
			let count = await dbUtil.getCount({
				collection: 't3ds-marketing-task-asset',
				where: {
					taskId,
					used: false
				},
				transaction
			})
			let assetId = ""
			if (count) {
				let asset = await dbUtil.getOne({
					collection: 't3ds-marketing-task-asset',
					field: {
						_id: true
					},
					where: {
						taskId,
						used: false
					}
				})
				assetId = asset._id
			} else {
				let asset = await dbUtil.getOne({
					collection: 't3ds-marketing-task-asset',
					field: {
						_id: true
					},
					where: {
						taskId
					}
				})
				assetId = asset._id
			}
			console.log('assetId', assetId)
			let data = {
				taskId,
				assetId,
				uid: this.uid,
				enableCheckLocation: !task.checkLocation || task.checkLocationTime == 2 ? false : true,
				createTime: Date.now(),
				createBy: this.uid,
				checkStatus:0
			}
			if (task.finishedLimitDays) {
				data.deadline = moment().add(task.finishedLimitDays, 'hours').toDate().getTime()
			}
			await dbUtil.insert({
				collection: 't3ds-marketing-task-user',
				data,
				transaction
			})
			await dbUtil.updateById({
				collection: 't3ds-marketing-task-asset',
				data: {
					_id: assetId,
					used: true,
					usedTime: Date.now()
				},
				transaction
			})
			let remainCount = task.amount
			if (task.remainCount != undefined) {
				remainCount -= 1
			}
			await dbUtil.updateById({
				collection: 't3ds-marketing-task',
				data: {
					_id: taskId,
					remainCount
				},
				transaction
			})
			await transaction.commit()
			return data
		} catch (err) {
			await transaction.rollback()
			return {
				errCode: 500,
				errMsg: err.message
			}
		}
	},
	
	async commit(id, medias, notes, userLocation) {
		if (!id || !medias || !Array.isArray(medias)) {
			return errParams
		}
		try {
			let userTask = await dbUtil.getById({
				collection: 't3ds-marketing-task-user',
				id
			})
			if (!userTask || userTask.uid != this.uid) {
				return errResNotFound
			}
			if (userTask.deadline) {
				if (Date.now() > userTask.deadline) {
					return {
						errCode: 506,
						errMsg: '已过完成任务截止时间，无法提交！'
					}
				}
			}
			if (userTask.checkRecords && userTask.checkRecords.length) {
				let r = userTask.checkRecords.pop()
				if (r.checkStatus != 0 && r.checkStatus != -1 && r.checkStatus != 3) {
					return {
						errCode: 502,
						errMsg: '请勿重复提交！'
					}
				}
			}
			let task = await dbUtil.getById({
				collection: 't3ds-marketing-task',
				id: userTask.taskId,
				field: {
					storeId: true,
					checkLocation: true
				}
			})
			if (task.checkLocation && (userTask.enableCheckLocation == undefined || userTask.enableCheckLocation) && (!userLocation || !userLocation.longitude || !userLocation.latitude)) {
				return {
					errCode: 504,
					errMsg: '请打开定位权限'
				}
			}
			if (task.checkLocation && (userTask.enableCheckLocation || userTask.enableCheckLocation == undefined)) {
				let storeInfo = await dbUtil.getById({
					collection: 't3ds-store',
					id: task.storeId,
					field: {
						location: true
					}
				})
				let distance = getDistance(userLocation, {
					latitude: storeInfo.location.latitude,
					longitude: storeInfo.location.longitude
				})
				console.log('distance', distance, userLocation, storeInfo.location.latitude, storeInfo.location.longitude)
				if (distance > 200) {
					return {
						errCode: 505,
						errMsg: '当前定位距离门店位置大于200米，不能提交！'
					}
				}
			}
			await dbUtil.updateById({
				collection: 't3ds-marketing-task-user',
				data: {
					_id: id,
					medias,
					notes,
					checkStatus:1,
					checkRecords: dbCmd.push({
						checkStatus: 1,
						commitTime: Date.now()
					})
				}
			})
		} catch (err) {
			return {
				errCode: 503,
				errMsg: err.message
			}
		}
	},
	
	async getUserTaskDetail(taskId, userLocation) {
		if (!taskId) {
			return {
				errCode: 500,
				errMsg: '参数错误！'
			}
		}
		
		try {
			let userTask = await dbUtil.getById({
				collection: 't3ds-marketing-task-user',
				id: taskId
			})
			if (!userTask) {
				return {
					errCode: 500,
					errMsg: '任务不存在！'
				}
			}
			let task = await dbUtil.getById({
				collection: 't3ds-marketing-task',
				id: userTask.taskId
			})
			task.received = true
			task.detailId = userTask._id
			task.medias = userTask.medias || []
			task.notes = userTask.notes || ''
			task.enableCheckLocation = userTask.enableCheckLocation
			if (userTask.checkRecords) {
				task.checkRecords = userTask.checkRecords
				let r = userTask.checkRecords[userTask.checkRecords.length - 1]
				task.checkStatus = r.checkStatus
				task.checkMsg = r.checkMsg
			} else {
				task.checkStatus = 0
				task.checkMsg = '未提交'
			}
			task.deadline = userTask.deadline || null
			if (userTask.assetId) {
				let asset = await dbUtil.getById({
					collection: 't3ds-marketing-task-asset',
					id: userTask.assetId,
					field: {
						images: true,
						text: true
					}
				})
				if (asset) {
					task.assetDetail = asset
				}
			}
			let storeInfo = await dbUtil.getById({
				collection: 't3ds-store',
				id: task.storeId,
				field: {
					name: true,
					address: true,
					location: true
				}
			})
			if (userLocation) {
				storeInfo.distance = getDistance(userLocation, {
					latitude: storeInfo.location.latitude,
					longitude: storeInfo.location.longitude
				})
			}
			task.storeInfo = storeInfo
			return task
		} catch (err) {
			return {
				errCode: 500,
				errMsg: err.message
			}
		}
	},
	
	async getTaskDetail(taskId, userLocation) {
		if (!taskId) {
			return {
				errCode: 500,
				errMsg: '参数错误！'
			}
		}
		
		try {
			let task = await dbUtil.getById({
				collection: 't3ds-marketing-task',
				id: taskId
			})
			if (!task) {
				return {
					errCode: 500,
					errMsg: '任务不存在！'
				}
			}
			// let userTask = await dbUtil.getOne({
			// 	collection: 't3ds-marketing-task-user',
			// 	where: {
			// 		taskId,
			// 		uid: this.uid
			// 	}
			// })
			let userTaskRes = await db.collection('t3ds-marketing-task-user')
				.aggregate()
				.match({
					taskId,
					uid: this.uid
				})
				.project({
					_id: 1,
					deadline: 1,
					medias: 1,
					notes: 1,
					assetId: 1,
					checkRecord: $.arrayElemAt(['$checkRecords', -1]),
				})
				.match({
					'checkRecord.checkStatus': dbCmd.neq(2)
				})
				.sort({
					createTime: -1
				})
				.limit(1)
				.end()
			let userTask = userTaskRes.data[0]
			if (userTask && (!userTask.deadline || userTask.deadline >= Date.now())) {
				task.received = true
				task.detailId = userTask._id
				task.medias = userTask.medias || []
				task.notes = userTask.notes || ''
				task.deadline = userTask.deadline
				if (userTask.checkRecord) {
					//task.checkRecords = userTask.checkRecords
					// let r = userTask.checkRecords[userTask.checkRecords.length - 1]
					task.checkStatus = userTask.checkRecord.checkStatus
					task.checkMsg = userTask.checkRecord.checkMsg
				} else {
					task.checkStatus = 0
					task.checkMsg = '未提交'
				}
				if (userTask.assetId) {
					let asset = await dbUtil.getById({
						collection: 't3ds-marketing-task-asset',
						id: userTask.assetId,
						field: {
							images: true,
							text: true
						}
					})
					if (asset) {
						task.assetDetail = asset
					}
				}
			} else {
				task.received = false
			}
			let storeInfo = await dbUtil.getById({
				collection: 't3ds-store',
				id: task.storeId,
				field: {
					name: true,
					address: true,
					location: true
				}
			})
			if (userLocation) {
				storeInfo.distance = getDistance(userLocation, {
					latitude: storeInfo.location.latitude,
					longitude: storeInfo.location.longitude
				})
			}
			task.storeInfo = storeInfo
			return task
		} catch (err) {
			return {
				errCode: 500,
				errMsg: err.message
			}
		}
	},

	async consumeIntegral(uid, storeId, amount, note) {
		amount = parseInt(amount)
		if (!uid || isNaN(amount) || amount <= 0 || !note || !note.trim()) {
			return errParams
		}
		let integral = await dbUtil.getOne({
			collection: 't3ds-integral',
			where: {
				uid,
				storeId
			}
		})
		if (!integral || integral.balance < amount) {
			return {
				errCode: 502,
				errMsg: '积分不足'
			}
		}
		let transaction = await db.startTransaction()
		try{
			// await dbUtil.updateById({
			// 	collection: 'uni-id-users',
			// 	data: {
			// 		_id: uid,
			// 		integral: dbCmd.inc(-amount)
			// 	},
			// 	transaction
			// })
			await dbUtil.updateById({
				collection: 't3ds-integral',
				data: {
					_id: integral._id,
					balance: dbCmd.inc(-amount)
				},
				transaction
			})
			await dbUtil.insert({
				collection: 't3ds-integral-log',
				data: {
					uid,
					storeId,
					type: -1,
					balance: integral.balance - amount,
					income: -amount,
					createTime: Date.now(),
					createBy: this.uid,
					note
				}
			})
			await transaction.commit()
		}catch(e){
			await transaction.rollback()
			return {
				errCode: 503,
				errMsg: e.message
			}
		}
	},
	
		
	async updateRelevancyUserById(taskId,uid){
		try{
			dbUtil.updateById({
				collection:'t3ds-marketing-task',
				data:{
					_id:taskId,
					relevancyUserId:uid
				}
			})
		}catch(e){
			//TODO handle the exception
			return {
				errCode: 503,
				errMsg: "修改失败"
			}
		}
		
	}

}